<!DOCTYPE html>
<html  lang="zh-CN" >
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
    content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <meta name="theme-color" content="#fff" id="theme-color">
  <meta name="description" content="深山磨柴斧，一鸣震江湖">
  <link rel="icon" href="/img/ic_head.jpg">
  <title>034-Android存储（9）：腾讯MMKV 高性能键值存储组件详解</title>
  
  
  <meta property="og:title" content="034-Android存储（9）：腾讯MMKV 高性能键值存储组件详解">
  
  
  <meta property="og:url" content="http://example.com/2019/10/22/034-Android%E5%AD%98%E5%82%A8%EF%BC%889%EF%BC%89%EF%BC%9A%E8%85%BE%E8%AE%AFMMKV%20%E9%AB%98%E6%80%A7%E8%83%BD%E9%94%AE%E5%80%BC%E5%AD%98%E5%82%A8%E7%BB%84%E4%BB%B6%E8%AF%A6%E8%A7%A3/index.html">
  
  
  <meta property="og:img" content="/img/ic_head.jpg">
  
  
  <meta property="og:img" content="深山磨柴斧，一鸣震江湖">
  
  
  <meta property="og:type" content="article">
  <meta property="og:article:published_time" content="2019-10-22">
  <meta property="og:article:modified_time" content="2021-04-14">
  <meta property="og:article:author" content="Cupster">
  
  
  <meta property="og:article:tag" content="Android">
  
  <meta property="og:article:tag" content="Android持久化">
  
  
  
  
  <script>
    // control reverse button
    var reverseDarkList = {
      dark: 'light',
      light: 'dark'
    };
    var themeColor = {
      dark: '#1c1c1e',
      light: '#fff'
    }
    // get the data of css prefers-color-scheme
    var getCssMediaQuery = function() {
      return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
    };
    // reverse current darkmode setting function
    var reverseDarkModeSetting = function() {
      var setting = localStorage.getItem('user-color-scheme');
      if(reverseDarkList[setting]) {
        setting = reverseDarkList[setting];
      } else if(setting === null) {
        setting = reverseDarkList[getCssMediaQuery()];
      } else {
        return;
      }
      localStorage.setItem('user-color-scheme', setting);
      return setting;
    };
    // apply current darkmode setting
    var setDarkmode = function(mode) {
      var setting = mode || localStorage.getItem('user-color-scheme');
      if(setting === getCssMediaQuery()) {
        document.documentElement.removeAttribute('data-user-color-scheme');
        localStorage.removeItem('user-color-scheme');
        document.getElementById('theme-color').content = themeColor[setting];
      } else if(reverseDarkList[setting]) {
        document.documentElement.setAttribute('data-user-color-scheme', setting);
        document.getElementById('theme-color').content = themeColor[setting];
      } else {
        document.documentElement.removeAttribute('data-user-color-scheme');
        localStorage.removeItem('user-color-scheme');
        document.getElementById('theme-color').content = themeColor[getCssMediaQuery()];
      }
    };
    setDarkmode();
  </script>
  <script>
    function loadScript(url, cb) {
      var script = document.createElement('script');
      script.src = url;
      if (cb) script.onload = cb;
      script.async = true;
      document.body.appendChild(script);
    }
  </script>
  
  <link rel="preload" href="//at.alicdn.com/t/font_1946621_i1kgafibvw.css" as="style" >
  <link rel="preload" href="//at.alicdn.com/t/font_1952792_89b4ac4k4up.css" as="style" >
  
  <link rel="preload" href="/js/lib/lightbox/baguetteBox.min.js" as="script">
  <link rel="preload" href="/js/lib/lightbox/baguetteBox.min.css" as="style" >
  
  
  <link rel="preload" href="/js/lib/lozad.min.js" as="script">
  
  
  
  
  
  
  
  
<link rel="stylesheet" href="/css/main.css">

  
  
<link rel="stylesheet" href="//at.alicdn.com/t/font_1946621_i1kgafibvw.css">

  
  
<link rel="stylesheet" href="//at.alicdn.com/t/font_1952792_89b4ac4k4up.css">

  
  
<link rel="stylesheet" href="/js/lib/lightbox/baguetteBox.min.css">

  
  
  
  
<meta name="generator" content="Hexo 5.4.0"></head>


<body>
  <div class="wrapper">
    
    <nav class="navbar">
  <div class="navbar-logo">
    <span class="navbar-logo-main">
      
      <img class="navbar-logo-img" src="/img/ic_head.jpg" alt="logo">
      
      <span class="navbar-logo-dsc">不负明天</span>
    </span>
  </div>
  <div class="navbar-menu">
    
    <a href="/" class="navbar-menu-item">
    
    首页
    
    </a>
    
    <a href="/archives" class="navbar-menu-item">
    
    归档
    
    </a>
    
    <a href="/tags" class="navbar-menu-item">
    
    标签
    
    </a>
    
    <a href="/categories" class="navbar-menu-item">
    
    分类
    
    </a>
    
    <a href="/about" class="navbar-menu-item">
    
    关于
    
    </a>
    
    <a href="/links" class="navbar-menu-item">
    
    友链
    
    </a>
    
    <a class="navbar-menu-item darknavbar" id="dark"><i class="iconfont icon-weather"></i></a>
    <a class="navbar-menu-item searchnavbar" id="search"><i class="iconfont icon-search" style="font-size: 1.2rem; font-weight: 400;"></i></a>
  </div>
</nav>
    
    <div id="local-search" style="display: none;">
      <input class="navbar-menu-item" id="search-input" placeholder="请输入搜索内容...">
      <div id="search-content"></div>
    </div>
    
    <div class="section-wrap">
      <div class="container">
        <div class="columns">
          <main class="main-column">
<article class="card card-content">
  <header>
    <h1 class="post-title">
      034-Android存储（9）：腾讯MMKV 高性能键值存储组件详解
    </h1>
  </header>
  <div class="post-meta post-show-meta">
    <time datetime="2019-10-22T04:53:11.000Z">
      <i class="iconfont icon-calendar" style="margin-right: 2px;"></i>
      <span>2019-10-22</span>
    </time>
    
    <span class="dot"></span>
    
    <a href="/categories/Android/" class="post-meta-link">Android</a>
    
    
    
    <span class="dot"></span>
    <span>2.7k 字</span>
    
  </div>
  
  <div class="post-meta post-show-meta" style="margin-top: -10px;">
    <div style="display: flex; align-items: center;">
      <i class="iconfont icon-biaoqian" style="margin-right: 2px; font-size: 1.15rem;"></i>
      
      
        <a href="/tags/Android/" class="post-meta-link">Android</a>
      
      
      <span class="dot"></span>
      
        <a href="/tags/Android持久化/" class="post-meta-link">Android持久化</a>
      
    </div>
  </div>
  
  </header>
  <div id="section" class="post-content">
    <p><a target="_blank" rel="noopener" href="https://cupster.blog.csdn.net/article/details/114987061">【5年Android从零复盘系列之三十四】Android存储（9）：腾讯MMKV 高性能键值存储组件详解</a></p>
<hr/>

<p>【代码是最好得老师】</p>
<h1 id="1-概要"><a href="#1-概要" class="headerlink" title="1.概要"></a>1.概要</h1><p><a target="_blank" rel="noopener" href="https://github.com/Tencent/MMKV">Github</a></p>
<p><a target="_blank" rel="noopener" href="https://github.com/Tencent/MMKV/blob/master/README.md">官方文档</a></p>
<p><a target="_blank" rel="noopener" href="https://download.csdn.net/download/Cupster/15904209">Demo.zip</a></p>
<ol>
<li>MMKV 是基于 mmap 内存映射的 key-value 组件</li>
<li>性能高，稳定性强（底层序列化/反序列化使用 protobuf 实现）</li>
<li>支持加密</li>
<li>支持多进程共享</li>
<li>支持匿名内存，内存悬浮不落地文件，安全性极高</li>
<li>效率极高</li>
<li>支持SharedPreferences直接迁移</li>
<li>支持类型：boolean、int、long、float、double、byte[]、String、Set<String>、Parcelable</li>
</ol>
<h1 id="2-对比-amp-原理"><a href="#2-对比-amp-原理" class="headerlink" title="2.对比&amp;原理"></a>2.对比&amp;原理</h1><p>数据来源腾讯官方测试数据</p>
<h2 id="2-1-单进程性能"><a href="#2-1-单进程性能" class="headerlink" title="2.1 单进程性能"></a>2.1 单进程性能</h2><p>可以直观看出MMKV性能秒杀SP、SQLite</p>
<p>（测试机器是 华为 Mate 20 Pro 128G，Android 10，每组操作重复 1k 次，时间单位是 ms。）</p>
<img src="https:/ srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://gitee.com/cupster/picbed/raw/master/uPic/20210318172430_VWhfRB.jpg" class="lozad post-image"/gitee.com/cupster/picbed/raw/master/uPic/20210318172430_VWhfRB.jpg"/>



<h2 id="2-2-多进程性能"><a href="#2-2-多进程性能" class="headerlink" title="2.2 多进程性能"></a>2.2 多进程性能</h2><p>亦可看出，多进程中，MMKV都远远超越 MultiProcessSharedPreferences &amp; SQLite &amp; SQLite.<br>MMKV 在 Android 多进程 key-value 存储组件上是不二之选</p>
<p>（测试机器是 华为 Mate 20 Pro 128G，Android 10，每组操作重复 1k 次，时间单位是 ms。）</p>
<img src="https:/ srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://gitee.com/cupster/picbed/raw/master/uPic/20210318172718_jYPZ4o.jpg" class="lozad post-image"/gitee.com/cupster/picbed/raw/master/uPic/20210318172718_jYPZ4o.jpg"/>


<h2 id="2-3-原理"><a href="#2-3-原理" class="headerlink" title="2.3 原理"></a>2.3 原理</h2><ul>
<li>内存准备</li>
</ul>
<p>通过 mmap 内存映射文件，提供一段可供随时写入的内存块，App 只管往里面写数据，由操作系统负责将内存回写到文件，不必担心 crash 导致数据丢失。</p>
<ul>
<li>数据组织</li>
</ul>
<p>数据序列化方面我们选用 protobuf 协议，pb 在性能和空间占用上都有不错的表现。</p>
<ul>
<li>写入优化</li>
</ul>
<p>考虑到主要使用场景是频繁地进行写入更新，我们需要有增量更新的能力。我们考虑将增量 kv 对象序列化后，append 到内存末尾。</p>
<ul>
<li>空间增长</li>
</ul>
<p>使用 append 实现增量更新带来了一个新的问题，就是不断 append 的话，文件大小会增长得不可控。我们需要在性能和空间上做个折中。</p>
<p>更多请移步<a target="_blank" rel="noopener" href="https://github.com/Tencent/MMKV/wiki/design">MMKV原理</a></p>
<h1 id="3-简单使用"><a href="#3-简单使用" class="headerlink" title="3.简单使用"></a>3.简单使用</h1><p>1.module的build.gradle导包</p>
<pre><code>dependencies &#123;
    implementation &#39;com.tencent:mmkv-static:1.2.7&#39;
&#125;
</code></pre>
<p>2.app的Application中初始化，也可选择自定义自定义路径初始化MMKV,见Demo封装的工具类</p>
<pre><code>public void onCreate() &#123;
    super.onCreate();
    //最简单方式
    String rootDir = MMKV.initialize(this);
&#125;
</code></pre>
<p>3.简单的使用：存取数据</p>
<pre><code>MMKV kv = MMKV.defaultMMKV();

kv.encode(&quot;bool&quot;, true);
boolean bValue = kv.decodeBool(&quot;bool&quot;);

kv.encode(&quot;int&quot;, Integer.MIN_VALUE);
int iValue = kv.decodeInt(&quot;int&quot;);

kv.encode(&quot;string&quot;, &quot;Hello from mmkv&quot;);
String str = kv.decodeString(&quot;string&quot;);
</code></pre>
<h1 id="4-高阶用法"><a href="#4-高阶用法" class="headerlink" title="4.高阶用法"></a>4.高阶用法</h1><p>同理，先导包</p>
<pre><code>dependencies &#123;
    implementation &#39;com.tencent:mmkv-static:1.2.7&#39;
&#125;
</code></pre>
<h2 id="4-1-初始化（日志、多进程、加密、分组存储）"><a href="#4-1-初始化（日志、多进程、加密、分组存储）" class="headerlink" title="4.1.初始化（日志、多进程、加密、分组存储）"></a>4.1.初始化（日志、多进程、加密、分组存储）</h2><p>在app的Application中初始化，也可选择自定义自定义路径初始化MMKV,见Demo封装的工具类</p>
<pre><code>public void onCreate() &#123;
    super.onCreate();
    //进阶方式1
    MMKVHelper.init(this);
    //进阶方式2
    String dir = getFilesDir().getAbsolutePath() + &quot;/mmkv_2&quot;;
    String rootDir = MMKVHelper.init(dir);
&#125;
</code></pre>
<p>MMKVHelper封装类.方法，涵盖加密、多进程使用情形</p>
<pre><code>public static  String ENCRPT_KEY = BuildConfig.LIBRARY_PACKAGE_NAME;//修改默认加密key
public static  String ENCRPT_KEY_MULTI_PROGRESS = BuildConfig.LIBRARY_PACKAGE_NAME;//修改默认加密key2

public static String init(Application context) &#123;
    return init(context ,&quot;&quot;,true ,ENCRPT_KEY);
&#125;

public static String init(String mmkvFilePath) &#123;
    return init(null,mmkvFilePath ,true ,ENCRPT_KEY);
&#125;

public static String init(Application context, String path ,boolean openLog ,String encryptKey) &#123;
    String rootDir ;
    if (TextUtils.isEmpty(path))&#123;
        rootDir = MMKV.initialize(context);
    &#125;else &#123;
        rootDir = MMKV.initialize(path);
    &#125;
    if (openLog) &#123;
        Log.d(&quot;MMKV root dir:&quot;, rootDir);
        MMKV.setLogLevel(MMKVLogLevel.LevelInfo);
    &#125;else &#123;
        //除非有非常强烈的证据表明MMKV的日志拖慢了App的速度，否则不应该关掉日志
        MMKV.setLogLevel(MMKVLogLevel.LevelNone);
    &#125;
    if (!TextUtils.isEmpty(encryptKey))&#123;
        ENCRPT_KEY = encryptKey;
        ENCRPT_KEY_MULTI_PROGRESS = encryptKey;
    &#125;
    return rootDir;
&#125;
</code></pre>
<h2 id="4-2-增删改查"><a href="#4-2-增删改查" class="headerlink" title="4.2.增删改查"></a>4.2.增删改查</h2><p>简单使用MMKV，默认配置都是单进程、不加密，封装类MMKVHelper进阶使用，开放便捷设置情况,完整代码见Demo封装类代码。</p>
<p>example:</p>
<h3 id="4-2-1-存储（增、改）："><a href="#4-2-1-存储（增、改）：" class="headerlink" title="4.2.1 存储（增、改）："></a>4.2.1 存储（增、改）：</h3><pre><code>public static boolean put(String key, String value) &#123;
    return MMKV.defaultMMKV(MMKV.SINGLE_PROCESS_MODE , ENCRPT_KEY).encode(key, value);
&#125;

public static boolean put(String key, int value) &#123;
    return MMKV.defaultMMKV(MMKV.SINGLE_PROCESS_MODE, ENCRPT_KEY).encode(key, value);
&#125;

//其他类型同理......

public static Boolean put2Group(String GroupId, String key, Object value) &#123;
    return put2Group(GroupId, key, value, false);
&#125;

//进阶
public static Boolean put2Group(String GroupId, String key, Object value, boolean multiProgress) &#123;
    MMKV mmkv;
    if (multiProgress) &#123;
        //如果业务需要多进程访问，那么在初始化的时候加上标志位 MMKV.MULTI_PROCESS_MODE
        mmkv = MMKV.mmkvWithID(GroupId, MMKV.MULTI_PROCESS_MODE, ENCRPT_KEY_MULTI_PROGRESS);
    &#125; else &#123;
        //默认单进程
        mmkv = MMKV.mmkvWithID(GroupId, MMKV.SINGLE_PROCESS_MODE, ENCRPT_KEY);
    &#125;

    boolean flag = false;
    if (value instanceof Boolean) &#123;
        flag = mmkv.encode(key, (Boolean) value);
    &#125;
    if (value instanceof Integer) &#123;
        flag = mmkv.encode(key, (int) value);
    &#125;
    if (value instanceof Float) &#123;
        flag = mmkv.encode(key, (Float) value);
    &#125;
    if (value instanceof Double) &#123;
        flag = mmkv.encode(key, (Double) value);
    &#125;
    if (value instanceof Long) &#123;
        flag = mmkv.encode(key, (Long) value);
    &#125;
    if (value instanceof String) &#123;
        flag = mmkv.encode(key, (String) value);
    &#125;
    if (value instanceof Parcelable) &#123;
        flag = mmkv.encode(key, (Parcelable) value);
    &#125;
    return flag;
&#125;
</code></pre>
<h3 id="4-2-2-删除"><a href="#4-2-2-删除" class="headerlink" title="4.2.2 删除"></a>4.2.2 删除</h3><pre><code> //delete simple
public static boolean delete(String deleteItemKey) &#123;
    MMKV.defaultMMKV(MMKV.SINGLE_PROCESS_MODE, ENCRPT_KEY).remove(deleteItemKey);
    return MMKV.defaultMMKV(MMKV.SINGLE_PROCESS_MODE, ENCRPT_KEY).contains(deleteItemKey);
&#125;

public static boolean delete(String groupId, String deleteItemKey) &#123;
    return delete(groupId, deleteItemKey, false);
&#125;

public static boolean delete(String groupId, String deleteItemKey, boolean multiProgress) &#123;
    int mode = multiProgress ? MMKV.MULTI_PROCESS_MODE : MMKV.SINGLE_PROCESS_MODE;
    MMKV mmkv;
    if (mode == MMKV.MULTI_PROCESS_MODE) &#123;
        mmkv = MMKV.mmkvWithID(groupId, MMKV.MULTI_PROCESS_MODE, ENCRPT_KEY_MULTI_PROGRESS);
    &#125; else &#123;
        mmkv = MMKV.mmkvWithID(groupId, mode, ENCRPT_KEY);
    &#125;
    mmkv.remove(deleteItemKey);
    return mmkv.contains(deleteItemKey);
&#125;
</code></pre>
<h3 id="4-2-3-获取（查询）"><a href="#4-2-3-获取（查询）" class="headerlink" title="4.2.3 获取（查询）"></a>4.2.3 获取（查询）</h3><p>基础获取、多进程获取、分组获取</p>
<pre><code>public static String get(String key, String defValue) &#123;
    return MMKV.defaultMMKV(MMKV.SINGLE_PROCESS_MODE , ENCRPT_KEY).decodeString(key, defValue);
&#125;

public static int get(String key, int defValue) &#123;
    return MMKV.defaultMMKV(MMKV.SINGLE_PROCESS_MODE, ENCRPT_KEY).decodeInt(key, defValue);
&#125;

public static &lt;T&gt; T getByGroup(String GroupId, String key, Object defValue) &#123;
    return (T) getByGroup(GroupId, key, defValue, false);
&#125;

public static Object getByGroup(String GroupId, String key, Object defValue, boolean multiProgress) &#123;
    MMKV mmkv;
    if (multiProgress) &#123;
        //如果业务需要多进程访问，那么在初始化的时候加上标志位 MMKV.MULTI_PROCESS_MODE
        mmkv = MMKV.mmkvWithID(GroupId, MMKV.MULTI_PROCESS_MODE, ENCRPT_KEY_MULTI_PROGRESS);
    &#125; else &#123;
        //默认单进程
        mmkv = MMKV.mmkvWithID(GroupId, MMKV.SINGLE_PROCESS_MODE, ENCRPT_KEY);
    &#125;

    if (defValue instanceof Boolean) &#123;
        return mmkv.decodeBool(key, (Boolean) defValue);
    &#125;
    if (defValue instanceof Integer) &#123;
        return mmkv.decodeInt(key, (int) defValue);
    &#125;
    if (defValue instanceof Float) &#123;
        return mmkv.decodeFloat(key, (Float) defValue);
    &#125;
    if (defValue instanceof Double) &#123;
        return mmkv.decodeDouble(key, (Double) defValue);
    &#125;
    if (defValue instanceof Long) &#123;
        return mmkv.decodeLong(key, (Long) defValue);
    &#125;
    if (defValue instanceof String) &#123;
        return mmkv.decodeString(key, (String) defValue);
    &#125;
    if (defValue instanceof Parcelable) &#123;
        return mmkv.decodeParcelable(key, (Class&lt;Parcelable&gt;) defValue);
    &#125;
    return null;
&#125;
</code></pre>
<h1 id="5-其他设置"><a href="#5-其他设置" class="headerlink" title="5.其他设置"></a>5.其他设置</h1><h2 id="5-1-SP迁移"><a href="#5-1-SP迁移" class="headerlink" title="5.1 SP迁移"></a>5.1 SP迁移</h2><p>SharedPreferences 迁移<br>MMKV 提供了 importFromSharedPreferences() 函数，可以比较方便地迁移数据过来。</p>
<p>MMKV 还额外实现了一遍 SharedPreferences、SharedPreferences.Editor 这两个 interface，在迁移的时候只需两三行代码即可，其他 CRUD 操作代码都不用改。</p>
<pre><code>private void testImportSharedPreferences() &#123;
    //SharedPreferences preferences = getSharedPreferences(&quot;myData&quot;, MODE_PRIVATE);
    MMKV preferences = MMKV.mmkvWithID(&quot;myData&quot;);
    // 迁移旧数据
    &#123;
        SharedPreferences old_man = getSharedPreferences(&quot;myData&quot;, MODE_PRIVATE);
        preferences.importFromSharedPreferences(old_man);
        old_man.edit().clear().commit();
    &#125;
    // 跟以前用法一样
    SharedPreferences.Editor editor = preferences.edit();
    editor.putBoolean(&quot;bool&quot;, true);
    editor.putInt(&quot;int&quot;, Integer.MIN_VALUE);
    editor.putLong(&quot;long&quot;, Long.MAX_VALUE);
    editor.putFloat(&quot;float&quot;, -3.14f);
    editor.putString(&quot;string&quot;, &quot;hello, imported&quot;);
    HashSet&lt;String&gt; set = new HashSet&lt;String&gt;();
    set.add(&quot;W&quot;); set.add(&quot;e&quot;); set.add(&quot;C&quot;); set.add(&quot;h&quot;); set.add(&quot;a&quot;); set.add(&quot;t&quot;);
    editor.putStringSet(&quot;string-set&quot;, set);
    // 无需调用 commit()
    //editor.commit();
&#125;
</code></pre>
<h2 id="5-2-日志"><a href="#5-2-日志" class="headerlink" title="5.2 日志"></a>5.2 日志</h2><p>MMKV 默认将日志打印到 logcat，不便于对线上问题进行定位和解决。你可以在 App 启动时接收转发 MMKV 的日志。实现MMKVHandler接口，添加类似下面的代码：</p>
<pre><code>@Override
public boolean wantLogRedirecting() &#123;
    return true;
&#125;

@Override
public void mmkvLog(MMKVLogLevel level, String file, int line, String func, String message) &#123;
    String log = &quot;&lt;&quot; + file + &quot;:&quot; + line + &quot;::&quot; + func + &quot;&gt; &quot; + message;
    switch (level) &#123;
        case LevelDebug:
            //Log.d(&quot;redirect logging MMKV&quot;, log);
            break;
        case LevelInfo:
            //Log.i(&quot;redirect logging MMKV&quot;, log);
            break;
        case LevelWarning:
            //Log.w(&quot;redirect logging MMKV&quot;, log);
            break;
        case LevelError:
            //Log.e(&quot;redirect logging MMKV&quot;, log);
            break;
        case LevelNone:
            //Log.e(&quot;redirect logging MMKV&quot;, log);
            break;
    &#125;
&#125;
</code></pre>
<p>日志组件推荐使用 <a target="_blank" rel="noopener" href="https://github.com/Tencent/mars#mars-xlog-1">xlog</a>，同样也是开源自微信团队。</p>
<p>关闭日志（不建议）：</p>
<p>除非有非常强烈的证据表明MMKV的日志拖慢了App的速度，否则不应该关掉日志。没有日志，日后万一用户有问题，将无法跟进。</p>
<pre><code>MMKV.setLogLevel(MMKVLogLevel.LevelNone);//关闭日志
</code></pre>
<h2 id="5-3-加密"><a href="#5-3-加密" class="headerlink" title="5.3 加密"></a>5.3 加密</h2><p>MMKV 默认明文存储所有 key-value，依赖 Android 系统的沙盒机制保证文件加密。如果你担心信息泄露，你可以选择加密 MMKV。</p>
<pre><code>String cryptKey = &quot;My-Encrypt-Key&quot;;
MMKV kv = MMKV.mmkvWithID(&quot;MyID&quot;, MMKV.SINGLE_PROCESS_MODE, cryptKey);
你可以更改密钥，也可以将一个加密 MMKV 改成明文，或者反过来。

final String mmapID = &quot;testAES_reKey1&quot;;
// an unencrypted MMKV instance
MMKV kv = MMKV.mmkvWithID(mmapID, MMKV.SINGLE_PROCESS_MODE, null);

// change from unencrypted to encrypted
kv.reKey(&quot;Key_seq_1&quot;);

// change encryption key
kv.reKey(&quot;Key_seq_2&quot;);

// change from encrypted to unencrypted
kv.reKey(null);
</code></pre>
<h2 id="5-4-自定义根目录"><a href="#5-4-自定义根目录" class="headerlink" title="5.4 自定义根目录"></a>5.4 自定义根目录</h2><p>MMKV 默认把文件存放在$(FilesDir)/mmkv/目录。你可以在 App 启动时自定义根目录：</p>
<pre><code>String dir = getFilesDir().getAbsolutePath() + &quot;/mmkv_2&quot;;
String rootDir = MMKV.initialize(dir);
Log.i(&quot;MMKV&quot;, &quot;mmkv root: &quot; + rootDir);
MMKV 甚至支持自定义某个文件的目录：

String relativePath = getFilesDir().getAbsolutePath() + &quot;/mmkv_3&quot;;
MMKV kv = MMKV.mmkvWithID(&quot;testCustomDir&quot;, relativePath);
</code></pre>
<p>注意：官方推荐将 MMKV 文件存储在你 App 的私有路径内部，不要 存储在 external storage（也就是 SD card）。</p>
<h2 id="5-5-自定义-library-loader"><a href="#5-5-自定义-library-loader" class="headerlink" title="5.5 自定义 library loader"></a>5.5 自定义 library loader</h2><p>一些 Android 设备（API level 19）在安装/更新 APK 时可能出错, 导致 libmmkv.so 找不到。然后就会遇到 java.lang.UnsatisfiedLinkError 之类的 crash。有个开源库 ReLinker 专门解决这个问题，你可以用它来加载 MMKV：</p>
<pre><code>String dir = getFilesDir().getAbsolutePath() + &quot;/mmkv&quot;;
MMKV.initialize(dir, new MMKV.LibLoader() &#123;
    @Override
    public void loadLibrary(String libName) &#123;
        ReLinker.loadLibrary(MyApplication.this, libName);
    &#125;
&#125;);
</code></pre>
<h2 id="5-6-Native-Buffer"><a href="#5-6-Native-Buffer" class="headerlink" title="5.6 Native Buffer"></a>5.6 Native Buffer</h2><p>当从 MMKV 取一个 String or byte[]的时候，会有一次从 native 到 JVM 的内存拷贝。如果这个值立即传递到另一个 native 库(JNI)，又会有一次从 JVM 到 native 的内存拷贝。当这个值比较大的时候，整个过程会非常浪费。Native Buffer 就是为了解决这个问题。<br>Native Buffer 是由 native 创建的内存缓冲区，在 Java 里封装成 NativeBuffer 类型，可以透明传递到另一个 native 库进行访问处理。整个过程避免了先拷内存到 JVM 又从 JVM 拷回来导致的浪费。示例代码:</p>
<pre><code>int sizeNeeded = kv.getValueActualSize(&quot;bytes&quot;);
NativeBuffer nativeBuffer = MMKV.createNativeBuffer(sizeNeeded);
if (nativeBuffer != null) &#123;
    int size = kv.writeValueToNativeBuffer(&quot;bytes&quot;, nativeBuffer);
    Log.i(&quot;MMKV&quot;, &quot;size Needed = &quot; + sizeNeeded + &quot; written size = &quot; + size);

    // pass nativeBuffer to another native library
    // ...

    // destroy when you&#39;re done
    MMKV.destroyNativeBuffer(nativeBuffer);
&#125;
</code></pre>
<h2 id="5-7-数据恢复"><a href="#5-7-数据恢复" class="headerlink" title="5.7 数据恢复"></a>5.7 数据恢复</h2><p>在 crc 校验失败，或者文件长度不对的时候，MMKV 默认会丢弃所有数据。你可以让 MMKV 恢复数据。要注意的是修复率无法保证，而且可能修复出奇怪的 key-value。同样地也是实现MMKVHandler接口，添加以下代码：</p>
<pre><code>@Override
public MMKVRecoverStrategic onMMKVCRCCheckFail(String mmapID) &#123;
    return MMKVRecoverStrategic.OnErrorRecover;
&#125;

@Override
public MMKVRecoverStrategic onMMKVFileLengthError(String mmapID) &#123;
    return MMKVRecoverStrategic.OnErrorRecover;
&#125;
</code></pre>
<h2 id="5-8-多进程与实现"><a href="#5-8-多进程与实现" class="headerlink" title="5.8 多进程与实现"></a>5.8 多进程与实现</h2><p><a target="_blank" rel="noopener" href="https://github.com/Tencent/MMKV/wiki/android_ipc">多进程设计与实现</a></p>
<h1 id="6-代码"><a href="#6-代码" class="headerlink" title="6.代码"></a>6.代码</h1><p><a target="_blank" rel="noopener" href="https://download.csdn.net/download/Cupster/15904209">Demo.zip</a></p>

  </div>
  <div>
  
  <div class="post-note note-warning copyright" style="margin-top: 42px">
    <p><span style="font-weight: bold;">作者：</span><a target="_blank" rel="nofollow noopener noreferrer" href="http://example.com/about">Cupster</a></p>
    <p><span style="font-weight: bold;">文章链接：</span><a target="_blank" rel="nofollow noopener noreferrer" href="http://example.com/2019/10/22/034-Android%E5%AD%98%E5%82%A8%EF%BC%889%EF%BC%89%EF%BC%9A%E8%85%BE%E8%AE%AFMMKV%20%E9%AB%98%E6%80%A7%E8%83%BD%E9%94%AE%E5%80%BC%E5%AD%98%E5%82%A8%E7%BB%84%E4%BB%B6%E8%AF%A6%E8%A7%A3/">http://example.com/2019/10/22/034-Android%E5%AD%98%E5%82%A8%EF%BC%889%EF%BC%89%EF%BC%9A%E8%85%BE%E8%AE%AFMMKV%20%E9%AB%98%E6%80%A7%E8%83%BD%E9%94%AE%E5%80%BC%E5%AD%98%E5%82%A8%E7%BB%84%E4%BB%B6%E8%AF%A6%E8%A7%A3/</a></p>
    <p><span style="font-weight: bold;">版权声明：</span>本博客所有文章除特别声明外，均采用<a target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh">CC BY-NC-SA 4.0 协议</a>。转载请注明出处！</p>
  </div>
  
  </div>
</article>
<div class="nav">
  
  <div class="nav-item-prev">
    <a href="/2020/03/01/Java过渡Kotlin01：基础语法/" class="nav-link">
      <i class="iconfont icon-left nav-prev-icon"></i>
      <div>
        <div class="nav-label">上一篇</div>
        
        <div class="nav-title">Java过渡Kotlin01：基础语法 </div>
        
      </div>
    </a>
  </div>
  
  
  <div class="nav-item-next">
    <a href="/2019/10/19/033-Android存储（8）：DBFlow使用详解/" class="nav-link">
      <div>
        <div class="nav-label">下一篇</div>
        
        <div class="nav-title">033-Android存储（8）：DBFlow使用详解 </div>
        
      </div>
      <i class="iconfont icon-right nav-next-icon"></i>
    </a>
  </div>
  
</div>

<div class="card card-content toc-card" id="mobiletoc">
  <div class="toc-header"><i class="iconfont icon-menu" style="padding-right: 2px;"></i>目录</div>
<ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#1-%E6%A6%82%E8%A6%81"><span class="toc-text">1.概要</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#2-%E5%AF%B9%E6%AF%94-amp-%E5%8E%9F%E7%90%86"><span class="toc-text">2.对比&amp;原理</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#2-1-%E5%8D%95%E8%BF%9B%E7%A8%8B%E6%80%A7%E8%83%BD"><span class="toc-text">2.1 单进程性能</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-2-%E5%A4%9A%E8%BF%9B%E7%A8%8B%E6%80%A7%E8%83%BD"><span class="toc-text">2.2 多进程性能</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-3-%E5%8E%9F%E7%90%86"><span class="toc-text">2.3 原理</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#3-%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8"><span class="toc-text">3.简单使用</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#4-%E9%AB%98%E9%98%B6%E7%94%A8%E6%B3%95"><span class="toc-text">4.高阶用法</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#4-1-%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%88%E6%97%A5%E5%BF%97%E3%80%81%E5%A4%9A%E8%BF%9B%E7%A8%8B%E3%80%81%E5%8A%A0%E5%AF%86%E3%80%81%E5%88%86%E7%BB%84%E5%AD%98%E5%82%A8%EF%BC%89"><span class="toc-text">4.1.初始化（日志、多进程、加密、分组存储）</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-2-%E5%A2%9E%E5%88%A0%E6%94%B9%E6%9F%A5"><span class="toc-text">4.2.增删改查</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-1-%E5%AD%98%E5%82%A8%EF%BC%88%E5%A2%9E%E3%80%81%E6%94%B9%EF%BC%89%EF%BC%9A"><span class="toc-text">4.2.1 存储（增、改）：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-2-%E5%88%A0%E9%99%A4"><span class="toc-text">4.2.2 删除</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-3-%E8%8E%B7%E5%8F%96%EF%BC%88%E6%9F%A5%E8%AF%A2%EF%BC%89"><span class="toc-text">4.2.3 获取（查询）</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#5-%E5%85%B6%E4%BB%96%E8%AE%BE%E7%BD%AE"><span class="toc-text">5.其他设置</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#5-1-SP%E8%BF%81%E7%A7%BB"><span class="toc-text">5.1 SP迁移</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-2-%E6%97%A5%E5%BF%97"><span class="toc-text">5.2 日志</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-3-%E5%8A%A0%E5%AF%86"><span class="toc-text">5.3 加密</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-4-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%B9%E7%9B%AE%E5%BD%95"><span class="toc-text">5.4 自定义根目录</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-5-%E8%87%AA%E5%AE%9A%E4%B9%89-library-loader"><span class="toc-text">5.5 自定义 library loader</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-6-Native-Buffer"><span class="toc-text">5.6 Native Buffer</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-7-%E6%95%B0%E6%8D%AE%E6%81%A2%E5%A4%8D"><span class="toc-text">5.7 数据恢复</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-8-%E5%A4%9A%E8%BF%9B%E7%A8%8B%E4%B8%8E%E5%AE%9E%E7%8E%B0"><span class="toc-text">5.8 多进程与实现</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#6-%E4%BB%A3%E7%A0%81"><span class="toc-text">6.代码</span></a></li></ol>
</div></main>
          <aside class="left-column">
            
            <div class="card card-author">
              
<img src="/img/ic_head.jpg" class="author-img">

<p class="author-name">Cupster</p>
<p class="author-description">深山磨柴斧，一鸣震江湖</p>
<div class="author-message">
  <a class="author-posts-count" href="/archives">
    <span>66</span>
    <span>文章</span>
  </a>
  <a class="author-categories-count" href="/categories">
    <span>5</span>
    <span>分类</span>
  </a>
  <a class="author-tags-count" href="/tags">
    <span>31</span>
    <span>标签</span>
  </a>
</div>

<div class="author-card-society">
  
    <div class="author-card-society-icon">
      <a target="_blank" rel="noopener" href="https://cupster.blog.csdn.net/">
        <i class="iconfont /img/ic_csdn.png society-icon"></i>
      </a>
    </div>
  
</div>

            </div>
            
            <div class="sticky-tablet">
  
  
  <article class="display-when-two-columns spacer">
    <div class="card card-content toc-card">
      <div class="toc-header"><i class="iconfont icon-menu" style="padding-right: 2px;"></i>目录</div>
<ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#1-%E6%A6%82%E8%A6%81"><span class="toc-text">1.概要</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#2-%E5%AF%B9%E6%AF%94-amp-%E5%8E%9F%E7%90%86"><span class="toc-text">2.对比&amp;原理</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#2-1-%E5%8D%95%E8%BF%9B%E7%A8%8B%E6%80%A7%E8%83%BD"><span class="toc-text">2.1 单进程性能</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-2-%E5%A4%9A%E8%BF%9B%E7%A8%8B%E6%80%A7%E8%83%BD"><span class="toc-text">2.2 多进程性能</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-3-%E5%8E%9F%E7%90%86"><span class="toc-text">2.3 原理</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#3-%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8"><span class="toc-text">3.简单使用</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#4-%E9%AB%98%E9%98%B6%E7%94%A8%E6%B3%95"><span class="toc-text">4.高阶用法</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#4-1-%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%88%E6%97%A5%E5%BF%97%E3%80%81%E5%A4%9A%E8%BF%9B%E7%A8%8B%E3%80%81%E5%8A%A0%E5%AF%86%E3%80%81%E5%88%86%E7%BB%84%E5%AD%98%E5%82%A8%EF%BC%89"><span class="toc-text">4.1.初始化（日志、多进程、加密、分组存储）</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-2-%E5%A2%9E%E5%88%A0%E6%94%B9%E6%9F%A5"><span class="toc-text">4.2.增删改查</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-1-%E5%AD%98%E5%82%A8%EF%BC%88%E5%A2%9E%E3%80%81%E6%94%B9%EF%BC%89%EF%BC%9A"><span class="toc-text">4.2.1 存储（增、改）：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-2-%E5%88%A0%E9%99%A4"><span class="toc-text">4.2.2 删除</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-3-%E8%8E%B7%E5%8F%96%EF%BC%88%E6%9F%A5%E8%AF%A2%EF%BC%89"><span class="toc-text">4.2.3 获取（查询）</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#5-%E5%85%B6%E4%BB%96%E8%AE%BE%E7%BD%AE"><span class="toc-text">5.其他设置</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#5-1-SP%E8%BF%81%E7%A7%BB"><span class="toc-text">5.1 SP迁移</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-2-%E6%97%A5%E5%BF%97"><span class="toc-text">5.2 日志</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-3-%E5%8A%A0%E5%AF%86"><span class="toc-text">5.3 加密</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-4-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%B9%E7%9B%AE%E5%BD%95"><span class="toc-text">5.4 自定义根目录</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-5-%E8%87%AA%E5%AE%9A%E4%B9%89-library-loader"><span class="toc-text">5.5 自定义 library loader</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-6-Native-Buffer"><span class="toc-text">5.6 Native Buffer</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-7-%E6%95%B0%E6%8D%AE%E6%81%A2%E5%A4%8D"><span class="toc-text">5.7 数据恢复</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-8-%E5%A4%9A%E8%BF%9B%E7%A8%8B%E4%B8%8E%E5%AE%9E%E7%8E%B0"><span class="toc-text">5.8 多进程与实现</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#6-%E4%BB%A3%E7%A0%81"><span class="toc-text">6.代码</span></a></li></ol>
    </div>
  </article>
  
  
  <article class="card card-content categories-widget">
    <div class="categories-card">
  <div class="categories-header"><i class="iconfont icon-fenlei" style="padding-right: 2px;"></i>分类</div>
  <div class="categories-list">
    
      <a href="/categories/Android/">
        <div class="categories-list-item">
          Android
          <span class="categories-list-item-badge">38</span>
        </div>
      </a>
    
      <a href="/categories/Linux/">
        <div class="categories-list-item">
          Linux
          <span class="categories-list-item-badge">6</span>
        </div>
      </a>
    
      <a href="/categories/Dev-Base/">
        <div class="categories-list-item">
          Dev-Base
          <span class="categories-list-item-badge">12</span>
        </div>
      </a>
    
      <a href="/categories/Kotlin/">
        <div class="categories-list-item">
          Kotlin
          <span class="categories-list-item-badge">9</span>
        </div>
      </a>
    
      <a href="/categories/自动化脚本/">
        <div class="categories-list-item">
          自动化脚本
          <span class="categories-list-item-badge">1</span>
        </div>
      </a>
    
  </div>
</div>
  </article>
  
  <article class="card card-content tags-widget">
    <div class="tags-card">
  <div class="tags-header"><i class="iconfont icon-biaoqian" style="padding-right: 2px;"></i>热门标签</div>
  <div class="tags-list">
    
    <a href="/tags/Android/" title="Android"><div class="tags-list-item">Android</div></a>
    
    <a href="/tags/Android自定义View/" title="Android自定义View"><div class="tags-list-item">Android自定义View</div></a>
    
    <a href="/tags/MacOS/" title="MacOS"><div class="tags-list-item">MacOS</div></a>
    
    <a href="/tags/Kotlin/" title="Kotlin"><div class="tags-list-item">Kotlin</div></a>
    
    <a href="/tags/Android持久化/" title="Android持久化"><div class="tags-list-item">Android持久化</div></a>
    
    <a href="/tags/CentOS/" title="CentOS"><div class="tags-list-item">CentOS</div></a>
    
    <a href="/tags/Linux/" title="Linux"><div class="tags-list-item">Linux</div></a>
    
    <a href="/tags/Android事件/" title="Android事件"><div class="tags-list-item">Android事件</div></a>
    
    <a href="/tags/Android基础/" title="Android基础"><div class="tags-list-item">Android基础</div></a>
    
    <a href="/tags/Android手势/" title="Android手势"><div class="tags-list-item">Android手势</div></a>
    
    <a href="/tags/Scrcpy/" title="Scrcpy"><div class="tags-list-item">Scrcpy</div></a>
    
    <a href="/tags/Android动画/" title="Android动画"><div class="tags-list-item">Android动画</div></a>
    
    <a href="/tags/Git/" title="Git"><div class="tags-list-item">Git</div></a>
    
    <a href="/tags/Java/" title="Java"><div class="tags-list-item">Java</div></a>
    
    <a href="/tags/Docker/" title="Docker"><div class="tags-list-item">Docker</div></a>
    
    <a href="/tags/Android-Dialog/" title="Android Dialog"><div class="tags-list-item">Android Dialog</div></a>
    
  </div>
</div>
  </article>
  
  
</div>
          </aside>
          <aside class="right-column">
            <div class="sticky-widescreen">
  
  
  <article class="card card-content toc-card">
    <div class="toc-header"><i class="iconfont icon-menu" style="padding-right: 2px;"></i>目录</div>
<ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#1-%E6%A6%82%E8%A6%81"><span class="toc-text">1.概要</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#2-%E5%AF%B9%E6%AF%94-amp-%E5%8E%9F%E7%90%86"><span class="toc-text">2.对比&amp;原理</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#2-1-%E5%8D%95%E8%BF%9B%E7%A8%8B%E6%80%A7%E8%83%BD"><span class="toc-text">2.1 单进程性能</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-2-%E5%A4%9A%E8%BF%9B%E7%A8%8B%E6%80%A7%E8%83%BD"><span class="toc-text">2.2 多进程性能</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-3-%E5%8E%9F%E7%90%86"><span class="toc-text">2.3 原理</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#3-%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8"><span class="toc-text">3.简单使用</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#4-%E9%AB%98%E9%98%B6%E7%94%A8%E6%B3%95"><span class="toc-text">4.高阶用法</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#4-1-%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%88%E6%97%A5%E5%BF%97%E3%80%81%E5%A4%9A%E8%BF%9B%E7%A8%8B%E3%80%81%E5%8A%A0%E5%AF%86%E3%80%81%E5%88%86%E7%BB%84%E5%AD%98%E5%82%A8%EF%BC%89"><span class="toc-text">4.1.初始化（日志、多进程、加密、分组存储）</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-2-%E5%A2%9E%E5%88%A0%E6%94%B9%E6%9F%A5"><span class="toc-text">4.2.增删改查</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-1-%E5%AD%98%E5%82%A8%EF%BC%88%E5%A2%9E%E3%80%81%E6%94%B9%EF%BC%89%EF%BC%9A"><span class="toc-text">4.2.1 存储（增、改）：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-2-%E5%88%A0%E9%99%A4"><span class="toc-text">4.2.2 删除</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-3-%E8%8E%B7%E5%8F%96%EF%BC%88%E6%9F%A5%E8%AF%A2%EF%BC%89"><span class="toc-text">4.2.3 获取（查询）</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#5-%E5%85%B6%E4%BB%96%E8%AE%BE%E7%BD%AE"><span class="toc-text">5.其他设置</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#5-1-SP%E8%BF%81%E7%A7%BB"><span class="toc-text">5.1 SP迁移</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-2-%E6%97%A5%E5%BF%97"><span class="toc-text">5.2 日志</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-3-%E5%8A%A0%E5%AF%86"><span class="toc-text">5.3 加密</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-4-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%B9%E7%9B%AE%E5%BD%95"><span class="toc-text">5.4 自定义根目录</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-5-%E8%87%AA%E5%AE%9A%E4%B9%89-library-loader"><span class="toc-text">5.5 自定义 library loader</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-6-Native-Buffer"><span class="toc-text">5.6 Native Buffer</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-7-%E6%95%B0%E6%8D%AE%E6%81%A2%E5%A4%8D"><span class="toc-text">5.7 数据恢复</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-8-%E5%A4%9A%E8%BF%9B%E7%A8%8B%E4%B8%8E%E5%AE%9E%E7%8E%B0"><span class="toc-text">5.8 多进程与实现</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#6-%E4%BB%A3%E7%A0%81"><span class="toc-text">6.代码</span></a></li></ol>
  </article>
  
  
  <article class="card card-content">
    <div class="recent-posts-card">
  <div class="recent-posts-header"><i class="iconfont icon-wenzhang_huaban" style="padding-right: 2px;"></i>最近文章</div>
  <div class="recent-posts-list">
    
      <div class="recent-posts-item">
        <div class="recent-posts-item-title">2021-03-02</div>
        <a href="/2021/03/02/Git commit规范/"><div class="recent-posts-item-content">Git commit规范</div></a>
      </div>
    
      <div class="recent-posts-item">
        <div class="recent-posts-item-title">2021-02-16</div>
        <a href="/2021/02/16/AutoJS一文精通AutoJS脚本教程详解/"><div class="recent-posts-item-content">AutoJS一文精通AutoJS脚本教程详解</div></a>
      </div>
    
      <div class="recent-posts-item">
        <div class="recent-posts-item-title">2021-01-21</div>
        <a href="/2021/01/21/架构师进阶：注解Annotation全解/"><div class="recent-posts-item-content">架构师进阶：注解Annotation全解</div></a>
      </div>
    
      <div class="recent-posts-item">
        <div class="recent-posts-item-title">2021-01-06</div>
        <a href="/2021/01/06/ConstraintLayout详解/"><div class="recent-posts-item-content">ConstraintLayout详解</div></a>
      </div>
    
  </div>
</div>
  </article>
  
  
</div>
          </aside>
        </div>
      </div>
    </div>
  </div>
  
  <footer class="footer">
  <div class="footer-container">
    <div>
      <div class="footer-dsc">
        <span>Copyright ©
          
          2020 -
          
          2021
        </span>
        &nbsp;
        <a href="/" class="footer-link">不负明天 </a>
      </div>
    </div>

    
    <div class="footer-dsc">
      
      Powered by
      <a href="https://hexo.io/" class="footer-link" target="_blank" rel="nofollow noopener noreferrer">&nbsp;Hexo </a>
      
      
      <span>&nbsp;|&nbsp;</span>
      
      
      Theme -
      <a href="https://github.com/theme-kaze" class="footer-link" target="_blank"
        rel="nofollow noopener noreferrer">&nbsp;Kaze</a>
      
    </div>
    
    
    
    
      <div class="footer-dsc">
        
        本站总访问量686<span id="busuanzi_value_site_pv"></span>次
        
        
        <span>&nbsp;|&nbsp;</span>
        
        
        本站总访客数219<span id="busuanzi_value_site_uv"></span>次
        
      </div>
      
    
</footer>
  <a role="button" id="scrollbutton" class="basebutton"  aria-label="回到顶部">
  <i class="iconfont icon-arrowleft button-icon"></i>
</a>
<a role="button" id="menubutton" class="basebutton">
  <i class="iconfont icon-menu button-icon"></i>
</a>
<a role="button" id="popbutton" class="basebutton" aria-label="控制中心">
  <i class="iconfont icon-expand button-icon"></i>
</a>
<a role="button" id="darkbutton" class="basebutton darkwidget" aria-label="夜色模式">
  <i class="iconfont icon-weather button-icon"></i>
</a>
<a role="button" id="searchbutton" class="basebutton searchwidget" aria-label="搜索">
  <i class="iconfont icon-search button-icon"></i>
</a>

  
  
  
  <script>
  var addImgLayout = function () {
    var img = document.querySelectorAll('.post-content img');
    var i;
    for (i = 0; i < img.length; i++) {
      var wrapper = document.createElement('a');
      wrapper.setAttribute('href', img[i].getAttribute('data-src'));
      wrapper.setAttribute('aria-label', 'illustration');
      wrapper.style.cssText = 'width: 100%; display: flex; justify-content: center;';
      if (img[i].alt) wrapper.dataset.caption = img[i].alt;
      wrapper.dataset.nolink = true;
      img[i].before(wrapper);
      wrapper.append(img[i]);
      var divWrap = document.createElement('div');
      divWrap.classList.add('gallery');
      wrapper.before(divWrap);
      divWrap.append(wrapper);
    }
    baguetteBox.run('.gallery');
  }
</script>
<script>loadScript("/js/lib/lightbox/baguetteBox.min.js", addImgLayout)</script>
  
  
  
<script src="/js/main.js"></script>

  
  <script>loadScript("/js/lib/busuanzi.min.js")</script>
  
  
  <script>
    var addLazyload = function () {
      var observer = lozad('.lozad', {
        load: function (el) {
          el.srcset = el.getAttribute('data-src');
        },
        loaded: function (el) {
          el.classList.add('loaded');
        }
      });
      observer.observe();
    }
  </script>
  <script>loadScript("/js/lib/lozad.min.js", addLazyload)</script>
  
  
</body>

</html>